package civilian;

import jade.core.AID;
import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.FailureException;
import jade.domain.FIPAAgentManagement.NotUnderstoodException;
import jade.domain.FIPAAgentManagement.RefuseException;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import jade.proto.AchieveREInitiator;
import jade.proto.AchieveREResponder;
import agents.UtilsAgents;
import building.Cell;
import building.InfoAgent;
import building.InfoGame;

/**
 * <p>
 * <B>Title:</b> Fire Evacuation
 * </p>
 * 
 * <p>
 * Civilian Agent
 * <p>
 * 
 * @author Carolina Arce & Caterina Bruno
 * @see building.InfoGame
 * @see ProtocolContractNetResponder
 */

public class CivilianAgent extends Agent implements java.io.Serializable {

	private static final long serialVersionUID = 1L;

	private int movements = 0;
	private int typeAgent = -1;
	private AID aid;
	private InfoGame game;
	private ProtocolContractNetResponder protocolContractNetResponder;

	/*** CODE CATE ******/

	private int anxiety;
	private int panic_stiken;
	private boolean injured;
	private boolean p_injured;
	private float healthy;
	private boolean dead;
	private boolean u18, a19_30, a31_79, o80; // fasce di et�
	private int mob_r;
	private UtilsAgents util;
	private int male;
	
	private boolean died = false;

	public void terminate() {
		doDelete();
	}

	public enum Age {
		UNDER_18, A19_30, A31_79, OVER80
	}

	private building.InfoAgent.Age age;

	public enum Gender {
		MALE, FEMALE
	}

	private building.InfoAgent.Gender gender;

	/*** CODE CAROLINA **********************/
	private boolean goal = false;

	private AID evacuatorAgent;

	/********************/

	public CivilianAgent() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * A message is shown in the log area of the GUI
	 * 
	 * @param str
	 *            String to show
	 */
	private void showMessage(String str) {
		System.out.println(getLocalName() + ": " + str);
	}

	protected void setup() {
		System.out.println(this.getLocalName() + " is ready.");
		// Register the agent to the DF
		ServiceDescription sd1 = new ServiceDescription();
		sd1.setType(agents.UtilsAgents.CIVILLIAN_AGENT);
		sd1.setName(getLocalName());
		sd1.setOwnership(UtilsAgents.OWNER);
		DFAgentDescription dfd = new DFAgentDescription();
		dfd.addServices(sd1);
		dfd.setName(getAID());
		this.aid = getAID();
		try {

			/****** CATE ************/
			Object args[] = getArguments();
			if (args != null && args.length > 0) {

				this.game = (InfoGame) getArguments()[0];
				if (this.game != null) {

					showMessage("Game: " + game.getInfo().getNumCivillians()
							+ " civilians");
				}
				game = (InfoGame) args[0];

				int ageRange = (Integer) args[1];

				male = (Integer) args[2];
				mob_r = (Integer) args[3];
				panic_stiken = (Integer) args[4];

				healthy = 100;
				if (ageRange == 0)
					age = building.InfoAgent.Age.OVER80;
				if (ageRange == 1)
					age = building.InfoAgent.Age.UNDER_18;
				if (ageRange == 2)
					age = building.InfoAgent.Age.A19_30;
				if (ageRange == 3)
					age = building.InfoAgent.Age.A31_79;

				if (male == 1)
					gender = building.InfoAgent.Gender.MALE;
				gender = building.InfoAgent.Gender.FEMALE;

				if (mob_r == 1) // true
				{
					healthy = 60;
				}

				else {
					healthy = 100; // false
				}

				this.p_injured = false;

				// System.err.println(this.getLocalName() + this.toString());
			}

			/****** CATE ************/
			DFService.register(this, dfd);
			showMessage(getLocalName() + "Agent Registered to the DF");

		} catch (FIPAException e) {
			System.err.println("Exception" + getLocalName()
					+ " registration with DF " + "unsucceeded. Reason: "
					+ e.getMessage());
			doDelete();
		}

		Object[] args = getArguments();

		if (args.length > 0) {
			this.game = (InfoGame) getArguments()[0];
			if (this.game != null) {

				showMessage("Tinc un joc amb "
						+ game.getInfo().getNumCivillians() + " civilians");
			}
		}
		// Adds a behavior to update game info each turn
		addTurnControl();

		// CONTRACTNET

		// protocolHelp = new ProtocolContractNetInitiator();

		protocolContractNetResponder = new ProtocolContractNetResponder();
		protocolContractNetResponder.addBehaviour(this);

		// protocolSendMove = new SendMovePetition();

		super.setup();
	}

	// TURN CONTROL
	public void addTurnControl() {
		MessageTemplate mt = MessageTemplate
				.MatchProtocol(agents.UtilsAgents.PROTOCOL_TURN);
		this.addBehaviour(new MessageReceiver(this, mt));
	}

	public boolean equals(CivilianAgent a) {
		return a.getAid().equals(this.aid);
	}

	public AID getAid() {
		return aid;
	}

	public void setAid(AID aid) {
		this.aid = aid;
	}

	public void setMovements(int movements) {
		this.movements = movements;
	}

	public int getMovements() {
		return movements;
	}

	public void setAID(AID aid) {
		this.aid = aid;
	}

	public int getAgentType() {
		return this.typeAgent;
	}

	public CivilianAgent getAgent() throws Exception {

		return this;

	}

	/*** CODE CATERINA ************************************/
	public boolean updateCiv_byInf(InfoAgent inf) {
		if (inf.getAID().equals(aid)) {
			this.mob_r = inf.reduceMob;

			this.age = inf.getAge();

			this.gender = inf.getGender();
			healthy = inf.healthy;

			this.panic_stiken = inf.getPanic();
			this.p_injured = inf.p_injured;
			// inf.setLastTurn(this.game.getInfo().getTurn());
			setInjured(inf.getInjured());
			System.err.println("AGENT " + aid.getLocalName() + "  INJ = "
					+ this.injured + "  INFOAG INJ " + inf.injured);
			died = inf.died;

			// System.err.println(this.toString());
			return true;
		}
		return false;
	}

	public boolean isInjured() {
		return injured;
	}

	public int getPanic_stiken() {
		return panic_stiken;
	}

	public void setPanic_stiken(int panic_stiken) {
		this.panic_stiken = panic_stiken;
	}

	public int getMob_r() {
		return mob_r;
	}

	public void setMob_r(int mob_r) {
		this.mob_r = mob_r;
	}

	public void setInjured(boolean injured) {
		this.injured = injured;
		if (this.injured) {
			System.err.println("SET INJURED::: AID " + this.getAID());
			Cell c = UtilsAgents.findAgent(this.getAID(), game);
			// System.err.println("setInjuredCivilian cell " );
			// game.addCenters(c);
			// System.err.println("CELL INJURED:  X " + c.getRow() + " Y " +
			// c.getColumn() );
		}
	}

	public float getHealthLevel() {

		/**
		 * Imposta il livello di salute in accordo alle fasi dell'incendio e
		 * alla fascia d'et� di appartenenza delle persone.
		 */
		int turn = game.getInfo().getTurn();
		if (turn < 200)
			this.healthy = (float) (this.healthy - ((this.healthy * 0.1) / 100));

		return this.healthy;

	}

	public void setHealty(int healty) {
		this.healthy = healty;
	}

	@Override
	public String toString() {

		return "CivilianAgent [aid=" + aid + ", panic_stiken=" + panic_stiken
				+ ", healty=" + healthy + ", mob_r=" + mob_r + ", male="
				+ this.gender.toString() + ", age=" + this.age.toString() + "]";
	}

	/*********** Other classes ********************************/
	class MessageReceiver extends AchieveREResponder {
		@Override
		protected ACLMessage prepareResultNotification(ACLMessage arg0,
				ACLMessage arg1) throws FailureException {
			return null;
		}

		@Override
		protected ACLMessage prepareResponse(ACLMessage arg0)
				throws NotUnderstoodException, RefuseException {
			 System.out.println("turn received"+arg0.getSender());
			ACLMessage response = arg0.createReply();
			AID evacuator = arg0.getSender();
			try {
				if (arg0.getContentObject() instanceof InfoGame) {
					 System.out.println("inicio la respuesta como civilian"+
					 this.myAgent.getLocalName()+ "/n" );
					response.setPerformative(ACLMessage.AGREE);
					game = (InfoGame) arg0.getContentObject();
					showMessage("New turn "+ game.getInfo().getTurn());
					/****** CATE ****/

					Cell c = UtilsAgents.findAgent(myAgent.getAID(), game);
					InfoAgent oldInfoAgent = c.getAgent();

					updateCiv_byInf(oldInfoAgent);
					if (oldInfoAgent.getPanic() >= 80) {

						// Sound myAlarm= new Sound("scream.wav");
						// myAlarm.playSoundOnce();
						// protocolHelp.addBehaviour(this.myAgent, c, game);
						// System.out.println("protocolo activo help" +
						// myAgent.getLocalName());
					}

					/*
					 * if(oldInfoAgent.imBlocked(myAgent.getAID(), game)) { /*
					 * List<Cell> receivers =
					 * oldInfoAgent.getNeighboors(myAgent.getAID(), game);
					 * if(receivers.size()>=1){ AID blockingAgent =
					 * receivers.get(0).getAgent().getAID();
					 * System.out.println("im sending an unblock message");
					 * protocolSendMove.addBehaviour(myAgent, blockingAgent);
					 * 
					 * } // Sound myAlarm= new Sound("scream.wav"); //
					 * myAlarm.playSoundOnce();
					 * //protocolHelp.addBehaviour(this.myAgent, c, game);
					 * //System.out.println("protocolo activo help" +
					 * myAgent.getLocalName()); }
					 */

					/****** CATE ****/

					protocolContractNetResponder.setInfoGame(game, evacuator);
					System.out.println("Civilian set info game civilian");

					// TODO you have the new game info on game

				} else {
					System.out.println("exception in civillian agent");
					throw new NotUnderstoodException(
							"Not the expected object type");

				}
			} catch (UnreadableException e) {
				response.setPerformative(ACLMessage.FAILURE);
				System.out.println("exceptiom1");
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				System.out.println("exceptiom2");
				e.printStackTrace();
			}

			return response;
		}

		private static final long serialVersionUID = -2066908850596603472L;

		public MessageReceiver(Agent arg0, MessageTemplate arg1) {
			super(arg0, arg1);
		}
	}

	public void setAge(building.InfoAgent.Age age) {
		this.age = age;
	}

	public void setGender(building.InfoAgent.Gender g) {
		this.gender = g;
	}

	/** OTHER CLASSES *****************/

	class MessageSender extends AchieveREInitiator {

		private static final long serialVersionUID = -8383729124578338150L;

		public MessageSender(Agent a, ACLMessage msg) {
			super(a, msg);
			// TODO Auto-generated constructor stub
		}

	}

	/**
	 * 
	 * User to inform the coordinator agent
	 */
	class Informer extends AchieveREInitiator {

		@Override
		protected void handleAgree(ACLMessage arg0) {
			showMessage("Evacuator received allarm");

			super.handleAgree(arg0);
		}

		@Override
		protected void handleInform(ACLMessage arg0) {
			// Auto-generated method stub
			// super.handleInform(arg0);
		}

		/**
         *
         */
		private static final long serialVersionUID = -8199039269513958089L;

		public Informer(Agent arg0, ACLMessage arg1) {
			super(arg0, arg1);
		}

	} // endof class turn control

}
